/*
 * GUI.java
 *
 * Created on Jan 1, 2011, 6:03:25 PM
 */

package hu.arguscab.game;

import hu.arguscab.ai.FitnessFunction;
import hu.arguscab.ai.Fitnessor;
import hu.arguscab.ai.game.Bot;
import hu.arguscab.ai.game.Command;
import hu.arguscab.graphic.NamedColor;
import java.awt.Color;
import javax.swing.DefaultListModel;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *
 * @author sharp
 */
public class GUI extends javax.swing.JFrame {

	GameScene scene;
	ApplicationContext context;
	DefaultListModel listModel = new DefaultListModel();
	DefaultListModel ffModel = new DefaultListModel();
	NamedColor[] supportedColors = new NamedColor[]{
	new NamedColor(Color.yellow, "Yellow"), new NamedColor(Color.BLACK, "Black"),
	new NamedColor(Color.BLUE, "Blue"), new NamedColor(Color.CYAN, "Cyan"),
	new NamedColor(Color.DARK_GRAY, "Dark gray"), new NamedColor(Color.GREEN, "Green"),
	new NamedColor(Color.WHITE, "White")};

	/**
	 * @param scene
	 */
    public GUI(GameScene scene) {
		this.scene = scene;
		this.context = new ClassPathXmlApplicationContext("beans/defaultAI.xml");

        initComponents();
		botList.setModel(listModel);
		ffList.setModel(ffModel);

		// Botok színei
		for (NamedColor c : supportedColors) {
			colorChooser.addItem(c);
		}

		// Command Combo box
		for ( Command c : Command.values() ) {
			commanCB.addItem(c);
		}
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        botList = new javax.swing.JList();
        addButton = new javax.swing.JButton();
        delButton = new javax.swing.JButton();
        colorChooser = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();
        fpsSpinner = new javax.swing.JSpinner();
        showTree = new javax.swing.JCheckBox();
        decisionDepthSpinner = new javax.swing.JSpinner();
        decisionTickSpinner = new javax.swing.JSpinner();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        ffList = new javax.swing.JList();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        ffWeight = new javax.swing.JTextField();
        commanCB = new javax.swing.JComboBox();
        delButton1 = new javax.swing.JButton();
        addButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        botList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                botListValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(botList);

        addButton.setText("Add");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        delButton.setText("Del");
        delButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                delButtonActionPerformed(evt);
            }
        });

        colorChooser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                colorChooserActionPerformed(evt);
            }
        });

        jLabel1.setText("FPS:");

        fpsSpinner.setValue(30);
        fpsSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                fpsSpinnerStateChanged(evt);
            }
        });

        showTree.setText("Show tree");
        showTree.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showTreeActionPerformed(evt);
            }
        });

        decisionDepthSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                decisionDepthSpinnerStateChanged(evt);
            }
        });

        decisionTickSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                decisionTickSpinnerStateChanged(evt);
            }
        });

        jLabel2.setText("DecisionDepth:");

        jLabel3.setText("DecisionTick:");

        ffList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                ffListValueChanged(evt);
            }
        });
        jScrollPane2.setViewportView(ffList);

        jLabel4.setText("Bots:");

        jLabel5.setText("Fitness Functions:");

        jLabel6.setText("weight:");

        ffWeight.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ffWeightActionPerformed(evt);
            }
        });

        commanCB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                commanCBActionPerformed(evt);
            }
        });

        delButton1.setText("Del");
        delButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                delButton1ActionPerformed(evt);
            }
        });

        addButton1.setText("Add");
        addButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(6, 6, 6)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(addButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(delButton, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel5)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 113, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(jLabel6)
                                        .addGap(3, 3, 3)
                                        .addComponent(ffWeight, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addGroup(layout.createSequentialGroup()
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                            .addComponent(addButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .addComponent(delButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addGap(18, 18, 18)
                                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                    .addComponent(jLabel3)
                                                    .addComponent(showTree))
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 32, Short.MAX_VALUE)
                                                .addComponent(decisionTickSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE))
                                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addComponent(jLabel2)
                                                .addGap(18, 18, 18)
                                                .addComponent(decisionDepthSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                .addGap(18, 18, 18)
                                                .addComponent(jLabel1)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                    .addComponent(fpsSpinner, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                    .addComponent(colorChooser, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)))))))
                            .addComponent(commanCB, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabel4)))
                .addContainerGap(34, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(addButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(delButton)))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(commanCB, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(colorChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel1)
                        .addComponent(fpsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(4, 4, 4)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel6)
                            .addComponent(ffWeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(addButton1)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(delButton1))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(decisionDepthSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jLabel2))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(jLabel3)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(showTree))
                                    .addComponent(decisionTickSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))))
                .addContainerGap(16, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
		Ship ship = context.getBean("AIShip", Ship.class);
		ship.getController().setName("Bot" + listModel.size());
		ship.randomPos();
		ship.setColor( (NamedColor) colorChooser.getSelectedItem() );
		scene.addShip(ship);
		listModel.addElement(ship);

	}//GEN-LAST:event_addButtonActionPerformed

	private void delButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_delButtonActionPerformed
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			scene.delShip(ship);
			listModel.removeElement(ship);
		}
	}//GEN-LAST:event_delButtonActionPerformed

	private void colorChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_colorChooserActionPerformed
		Ship ship = (Ship)botList.getSelectedValue();
		if ( ship != null ) {
			ship.setColor( (NamedColor) colorChooser.getSelectedItem());
		}

	}//GEN-LAST:event_colorChooserActionPerformed

	private void fpsSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_fpsSpinnerStateChanged
		scene.setTickPerSec((Integer)fpsSpinner.getValue());

	}//GEN-LAST:event_fpsSpinnerStateChanged

	private void showTreeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showTreeActionPerformed
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			if ( showTree.isSelected() ) {
				((Bot)(ship.getController())).setDrawVisualTree(true);
			} else {
				((Bot)(ship.getController())).setDrawVisualTree(false);
			}
		}

	}//GEN-LAST:event_showTreeActionPerformed

	private void decisionDepthSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_decisionDepthSpinnerStateChanged
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			int depth = (Integer)decisionDepthSpinner.getValue();
			((Bot)(ship.getController())).getDecisionTree().getTerminator().setMaxDepth(depth);
		}
	}//GEN-LAST:event_decisionDepthSpinnerStateChanged

	private void decisionTickSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_decisionTickSpinnerStateChanged
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			int tick = (Integer)decisionTickSpinner.getValue();
			((Bot)(ship.getController())).setDecisionTick(tick);
		}
	}//GEN-LAST:event_decisionTickSpinnerStateChanged

	private void botListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_botListValueChanged
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			Bot bot = ((Bot)(ship.getController()));
			// color
			NamedColor shipColor = getColor(ship);
			colorChooser.setSelectedItem(shipColor);

			// drawVisualTree
			showTree.setSelected(bot.isDrawVisualTree());

			// DecisionDepth
			int depth = bot.getDecisionTree().getTerminator().getMaxDepth();
			decisionDepthSpinner.setValue(depth);

			// DecisionTick
			int tick = bot.getDecisionTick();
			decisionTickSpinner.setValue(tick);

			// FF List
			fillFFList();
		}
}//GEN-LAST:event_botListValueChanged

	private void ffListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_ffListValueChanged
		FitnessFunction func = (FitnessFunction) ffList.getSelectedValue();
		if ( func != null )
			ffWeight.setText( ((Float)func.getWeight()).toString()  );
	}//GEN-LAST:event_ffListValueChanged

	private void commanCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_commanCBActionPerformed
		fillFFList();
	}//GEN-LAST:event_commanCBActionPerformed

	private void fillFFList() {
		ffModel.removeAllElements();
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			Bot bot = ((Bot)(ship.getController()));
			Command cmd = (Command) commanCB.getSelectedItem();
			Fitnessor fitnessor = bot.getFitnessors(cmd);
			for ( FitnessFunction func : fitnessor.getFitnessFunctions() ) {
				ffModel.addElement(func);
			}
		}
	}

	private void ffWeightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ffWeightActionPerformed
		float weight = Float.valueOf( ffWeight.getText() );
		FitnessFunction func = (FitnessFunction) ffList.getSelectedValue();
		if ( func != null )
			func.setWeight(weight);
	}//GEN-LAST:event_ffWeightActionPerformed

	private void delButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_delButton1ActionPerformed
		Ship ship = (Ship) botList.getSelectedValue();
		if ( ship != null ) {
			Bot bot = ((Bot)(ship.getController()));
			Command cmd = (Command) commanCB.getSelectedItem();
			Fitnessor fitnessor = bot.getFitnessors(cmd);
			FitnessFunction func = (FitnessFunction) ffList.getSelectedValue();
			if ( func != null ) {
				fitnessor.delFitnessFunction(func);
				ffModel.removeElement(func);
			}
		}
	}//GEN-LAST:event_delButton1ActionPerformed

	private void addButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButton1ActionPerformed
		// TODO add your handling code here:
	}//GEN-LAST:event_addButton1ActionPerformed

	private NamedColor getColor(Ship ship) {
		NamedColor shipColor = ship.getColor();
		for ( NamedColor c : supportedColors ) {
			if ( c.getRGB() == shipColor.getRGB() && c.getName().equals(shipColor.getName()) )
				return c;
		}
		assert false : "A hajó színe nem volt a listában!";
		return null;
	}

	public static void init(GameScene scene) {
		new GUI(scene).setVisible(true);
	}

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addButton;
    private javax.swing.JButton addButton1;
    private javax.swing.JList botList;
    private javax.swing.JComboBox colorChooser;
    private javax.swing.JComboBox commanCB;
    private javax.swing.JSpinner decisionDepthSpinner;
    private javax.swing.JSpinner decisionTickSpinner;
    private javax.swing.JButton delButton;
    private javax.swing.JButton delButton1;
    private javax.swing.JList ffList;
    private javax.swing.JTextField ffWeight;
    private javax.swing.JSpinner fpsSpinner;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JCheckBox showTree;
    // End of variables declaration//GEN-END:variables

}
